package com.link.base.core.RSAUtils;

import com.alibaba.fastjson.JSONObject;
import com.link.base.core.basic.util.YmlConstants;
import com.link.base.user.model.CoreUser;
import com.link.base.base.accnt.DmpField;
import com.link.base.base.rsasecretkey.model.RSASecretKey;
import com.link.core.basic.interceptor.SecurityInterceptor;
import com.link.core.basic.model.BasicModel;
import com.link.core.basic.service.BasicServiceException;
import com.link.core.util.*;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 *  DMP密钥方法工具类
 * @author Ninglanhao
 * @date 2019/3/25 11:51
 */
public class SecretKeyUtil {
    private static final Logger logger = LogManager.getLogger(SecretKeyUtil.class);

    /** DMP 关键参数key*/
    public static final String DMP_KEY_MSG = "msg";
    /** DMP 关键参数key*/
    public static final String DMP_KEY_AES_KEY = "aesKey";
    /** http请求头 Authorization*/
    public static final String HTTP_HEADER_AUTH = "Authorization";
    /** http请求头 Message*/
    public static final String HTTP_HEADER_MSG = "Message";
    /**link 登陆用户的token*/
    public static final String LINK_BASE_TOKEN = "Link-Base-Authorization";

    /**
     *  获得当前用户登陆时的dmpEncode
     *
     * @author NingLanhao
     * @date 2019-03-25 14:10
     * @param headId 头ID
     * @param headIdName 头对象名称
     * @return java.util.Map
     */
    public static Map<String, String> currentUserDmpEncode(String headIdName,String headId) throws Exception {
        // 默认值
        headId = StringUtils.isBlank(headId) ? "50606733285916672" : headId;
        headIdName = StringUtils.isBlank(headIdName) ? "acctId" : headIdName;

        CoreUser user = UserUtil.getUser();
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("userId", user.getId());
        jsonObject.put("postnId", user.getPostnId());
        jsonObject.put("orgId", user.getOrgId());
        jsonObject.put("headIdName", headIdName);
        jsonObject.put("headId", headId);
        jsonObject.put("corpId", user.getLoginCorpId());
        return getDmpEncode(jsonObject);
    }

    /**
     * 根据Json对象生成dmpEncode
     *
     * @author NingLanhao
     * @date 2019-03-25 14:12
     * @param jsonObject json对象
     * @return java.util.Map
     */
    public static Map<String, String> getDmpEncode(JSONObject jsonObject) throws Exception {
        RSASecretKey secretKey = new RSASecretKey();
        Date dNow = new Date();
        secretKey.setDate(dNow);
        secretKey.setEffectiveTime(YmlConstants.getDmpKeyExpires());
        secretKey.setMsg(jsonObject);
        String secretStr = JsonUtil.toString(secretKey);
        Map<String, String> map = DmpDecode.dmpEncode(secretStr);
        return map;
    }

    /**
     * DMP发送请求，具有默认header
     *
     * @author NingLanhao
     * @date 2019-03-27 20:15
     * @param url 路径
     * @param jsonParam json格式参数
     * @return java.util.Map
     */
    public static Map<String, Object> dmpHttpPostWithDefault(String url, JSONObject jsonParam) throws Exception {
        Map<String, String> encodeMap = currentUserDmpEncode(null, null);
        Map<String, String> headerMap = new HashMap<>(2);
        headerMap.put(HTTP_HEADER_AUTH, encodeMap.get(DMP_KEY_AES_KEY));
        headerMap.put(HTTP_HEADER_MSG, encodeMap.get(DMP_KEY_MSG));
        headerMap.put(LINK_BASE_TOKEN, SecurityInterceptor.token.get());
        return HttpRequestUtil.dmpHttpPost(url, jsonParam, headerMap);
    }

    /**
     * dmp 参数工具类
     *
     * @author NingLanhao
     * @date 2019-04-02 15:58
     */
    public static class DmpParamUtil {
        /**
         * 将对象中标注DmpField的变量存入map中
         *
         * @author NingLanhao
         * @date 2019-04-02 16:22
         * @param entity
         * @param param
         */
        public static void transformDmpAnnotationField(BasicModel entity, Map param) {
            Class<? extends BasicModel> clazz = entity.getClass();
            Field[] fields = clazz.getDeclaredFields();
            for (Field field : fields) {
                if (field.isAnnotationPresent(DmpField.class)) {
                    // link字段名
                    String fieldName = field.getName();
                    // 对应get方法
                    String getMethodName;
                    if (fieldName.startsWith("xAttr")) {
                        getMethodName = "get" + fieldName;
                    } else {
                        getMethodName = "get" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1, fieldName.length());
                    }
                    // link字段值
                    String linkValue = null;
                    try {
                        Method method = clazz.getMethod(getMethodName);
                        Object valueObj = method.invoke(entity, new Object[]{});
                        linkValue = valueObj == null ? "" : valueObj.toString();
                    } catch (NoSuchMethodException e) {
                        throw new BasicServiceException("不存在【" + getMethodName + "】此方法");
                    } catch (IllegalAccessException e) {
                        throw new BasicServiceException("【" + getMethodName + "】方法执行失败");
                    } catch (InvocationTargetException e) {
                        throw new BasicServiceException("【" + getMethodName + "】方法执行失败");
                    }
                    DmpField annotation = field.getAnnotation(DmpField.class);
                    // dmp对应字段名，作为map的KEY
                    String dmpFieldName = annotation.fieldName();
                    logger.info("param.put(\"" + dmpFieldName + "\", " + linkValue + ");");
                    param.put(dmpFieldName, linkValue);
                }
            }
        }
    }
}
